package com.yuyou.fn.wx.controller;

import com.yuyou.fn.wx.service.IWeixinService;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by wens on 2017/3/6.
 */
@Controller
public class WxMpPortalController {

    @Resource
    private IWeixinService weixinService;

    private static final Logger log = LoggerFactory.getLogger(WxMpPortalController.class);


    @RequestMapping(method = RequestMethod.GET, value = "/wechat/portal", produces = "text/plain;charset=utf-8")
    @ResponseBody
    public String authGet(@RequestParam(name = "signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr, HttpServletRequest request) {
        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }

        if (weixinService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }

        return "非法请求";
    }


    @RequestMapping(method = RequestMethod.POST, value = "/wechat/portal", produces = "application/xml;charset=UTF-8")
    @ResponseBody
    public String post(@RequestBody String requestBody, @RequestParam("signature") String signature,
                       @RequestParam(name = "encrypt_type", required = false) String encType,
                       @RequestParam(name = "msg_signature", required = false) String msgSignature,
                       @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
        log.info("\n接收微信请求：[signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!weixinService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        String out = null;
        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = weixinService.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toXml();
        } else if ("aes".equals(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody,
                    weixinService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);
            log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
            WxMpXmlOutMessage outMessage = weixinService.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toEncryptedXml(weixinService.getWxMpConfigStorage());
        }

        log.debug("\n组装回复信息：{}", out);

        return out;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/wechat/oauth2")
    public String oauth2(@RequestParam("redirectUrl") String redirectUrl, @RequestParam(value = "needUserInfo" , required = false ,defaultValue = "false") Boolean needUserInfo , HttpServletRequest request) throws UnsupportedEncodingException {

        String nginxPrefix = request.getHeader("nginx-prefix") ;

        if(nginxPrefix == null ){
            nginxPrefix = StringUtils.EMPTY ;
        }

        String redirect = StringUtils.replace(request.getRequestURL().toString(), request.getRequestURI(), nginxPrefix  +  "/wechat/oauth2/getCode?redirectUrl=" + (URLEncoder.encode(redirectUrl, "utf-8")));

        String authorizationUrl = weixinService.oauth2buildAuthorizationUrl(redirect,needUserInfo ?  WxConsts.OAUTH2_SCOPE_USER_INFO : WxConsts.OAUTH2_SCOPE_BASE , null);

        return "redirect:" + authorizationUrl;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/wechat/oauth2/getCode")
    public String oauth2GetCode(@RequestParam("code") String code, @RequestParam("redirectUrl") String redirectUrl) throws WxErrorException, UnsupportedEncodingException {

        WxMpOAuth2AccessToken oauth2getAccessToken = weixinService.oauth2getAccessToken(code);


        WxMpUser wxMpUser = weixinService.oauth2getUserInfo(oauth2getAccessToken, "zh_CN");

        StringBuilder wxParams = new StringBuilder();
        wxParams.append("openId=").append(wxMpUser.getOpenId());
        wxParams.append("&nickname=").append(URLEncoder.encode(wxMpUser.getNickname(),"utf-8" ));
        wxParams.append("&sex=").append(URLEncoder.encode(wxMpUser.getSex(),"utf-8" ));
        wxParams.append("&headImgUrl=").append(URLEncoder.encode( wxMpUser.getHeadImgUrl(),"utf-8" ));
        wxParams.append("&country=").append(URLEncoder.encode(wxMpUser.getCountry(),"utf-8" ));
        wxParams.append("&province=").append(URLEncoder.encode(wxMpUser.getProvince(),"utf-8" ));
        wxParams.append("&city=").append(wxMpUser.getCity());

        redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");

        String[] urls = redirectUrl.split("#");

        if(urls[0].contains("?")){
            urls[0] += "&" + wxParams.toString();
        }else{
            urls[0] += "?" + wxParams.toString();
        }
        return "redirect:" + StringUtils.join(urls , "#");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/wechat/config")
    @ResponseBody
    public Map<String,Object> config(@RequestParam("signatureUrl") String signatureUrl,HttpServletResponse response ) throws WxErrorException, UnsupportedEncodingException {

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.addHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers,If-Modified-Since, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers,accessToken");

        signatureUrl = URLDecoder.decode(signatureUrl ,"utf-8");
        WxJsapiSignature jsapiSignature = weixinService.createJsapiSignature(signatureUrl);
        Map<String,Object> ret = new HashMap<>();
        ret.put("debug" ,true );
        ret.put("appId" , jsapiSignature.getAppId());
        ret.put("timestamp", jsapiSignature.getTimestamp());
        ret.put("signature",jsapiSignature.getSignature());
        ret.put("nonceStr",jsapiSignature.getNonceStr());
        return ret ;
    }




}

